package com.briup.server.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.briup.common.response.ResultCode;
import com.briup.common.utils.AssertUtil;
import com.briup.common.utils.BeanUtil;
import com.briup.server.domain.bean.Role;
import com.briup.server.domain.bean.RoleMenu;
import com.briup.server.domain.dto.RoleModifiedDTO;
import com.briup.server.domain.dto.ConditionQueryDTO;
import com.briup.server.domain.vo.MenuVO;
import com.briup.server.domain.vo.RoleDetailVO;
import com.briup.server.mapper.RoleMapper;
import com.briup.server.mapper.RoleMenuMapper;
import com.briup.server.security.SecurityContext;
import com.briup.server.service.RoleMenuService;
import com.briup.server.service.RoleService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role>
        implements RoleService {

    private final RoleMenuMapper roleMenuMapper;
    private final RoleMenuService roleMenuService;

    @Override
    public List<RoleDetailVO> queryByIds(List<Long> roleIds) {
        // 校验角色ID列表是否为空
        AssertUtil.isTrue(!roleIds.isEmpty(), "角色ID列表不能为空");
        // 查询角色列表
        List<Role> roles = listByIds(roleIds);
        // 转换为角色详情VO列表，包含菜单权限
        return roles.stream()
                .map(this::convertToRoleDetailVO).toList();
    }

    @Override
    public Page<RoleDetailVO> pageQuery(ConditionQueryDTO queryDTO) {
        // 创建分页对象
        Page<Role> page = new Page<>(queryDTO.getPage(), queryDTO.getSize());
        // 构建查询条件
        LambdaQueryWrapper<Role> wrapper = null;
        if (StringUtils.hasText(queryDTO.getName())) {
            wrapper = Wrappers.lambdaQuery(Role.class)
                    .like(Role::getName, queryDTO.getName())
                    .or()
                    .like(Role::getRemark, queryDTO.getName());
        }
        // 执行分页查询，存在查询条件时会自动添加查询条件
        page(page, wrapper);

        Page<RoleDetailVO> detailVOPage = new Page<>(page.getCurrent(), page.getSize());
        // 将查询结果转换为角色详情VO列表
        detailVOPage.setRecords(page.getRecords().stream()
                .skip((page.getCurrent() - 1) * page.getSize())
                .limit(page.getSize())
                .map(this::convertToRoleDetailVO).toList());
        // 设置分页对象的总记录数，应该是符合条件的角色总数
        detailVOPage.setTotal(count(wrapper));
        return detailVOPage;
    }

    @Transactional
    @Override
    public void saveOrUpdateRole(RoleModifiedDTO modifiedDTO) {
        // 校验角色是否存在，是否存在同名的角色
        checkIsExists(modifiedDTO);
        // bean转换
        Role role = BeanUtil.convert(modifiedDTO, Role.class);
        if (modifiedDTO.getId() == null) {
            role.setCreateUserId(SecurityContext.userId());
            role.setCreateTime(LocalDateTime.now());
        }
        // 新增或修改角色信息
        saveOrUpdate(role);
        // 绑定角色和菜单的关系，即给角色绑定权限
        roleMenuService.grantPermissions(role.getId(), modifiedDTO.getMenuIds());
    }

    @Transactional
    @Override
    public void removeRole(List<Long> ids) {
        // 先在角色权限桥表中删除 角色id列表中的管理数据
        roleMenuService.remove(Wrappers.<RoleMenu>lambdaQuery()
                .in(RoleMenu::getRoleId, ids));
        // 在批量删除角色表中的数据
        removeByIds(ids);
    }

    private void checkIsExists(RoleModifiedDTO modifiedDTO) {
        if (modifiedDTO.getId() != null) {
            // 根据id查询角色信息，确保该角色存在
            Role role = getById(modifiedDTO.getId());
            AssertUtil.notNull(role, ResultCode.ROLE_IS_NOT_EXISTS);
        }
        // 构建条件构造器，确保角色名称不会存在重复
        LambdaQueryWrapper<Role> wrapper = Wrappers.<Role>lambdaQuery()
                .eq(Role::getName, modifiedDTO.getName())
                .ne(modifiedDTO.getId() != null,
                        Role::getId, modifiedDTO.getId());
        Role role = getOne(wrapper);
        AssertUtil.isTrue(role == null, ResultCode.ROLE_IS_EXISTS);
    }

    private RoleDetailVO convertToRoleDetailVO(Role role) {
        // 转换为角色详情VO，忽略menuList属性，因为该属性在后续会被设置，同时在Role实体中没有对应的属性
        RoleDetailVO detailVO = BeanUtil.convert(role, RoleDetailVO.class,
                "menuList");
        // 查询角色对应的菜单权限
        List<MenuVO> menuVOList = roleMenuMapper.queryMenuVOsByRoleId(role.getId())
                .stream()
                .distinct().collect(Collectors.toList());
        detailVO.setMenuList(menuVOList);
        return detailVO;
    }
}




